#!/usr/bin/env python
# -*- coding: utf-8 -*-

# import
import os
import web
import sys
import urllib
import json

# common
from common.log import log
from common.db.db import Db
from common.const import Const
from common.util import Util

# module
from control.master import Master

defaultencoding = 'utf-8'
if sys.getdefaultencoding() != defaultencoding:
    reload(sys)
    sys.setdefaultencoding(defaultencoding)

# web.py
urls = (
    "/vis/(.+)",
    "VISDispather",
    "/callback/(.+)",
    "CallbackDispather",
)

app = web.application(urls, globals())

vis_master = None


class VISDispather:
    '''VIS Dispather'''

    def GET(self, args):
        methods_disallow_log = []
        if args not in methods_disallow_log:
            log.debug('GET [%s]' % args)

        # 返回码和数据
        ret_code, ret_data = 1000, None

        # 参数获取
        params = web.input()
        token = (params['token'] if 'token' in params else '')
        username = (params['username'] if 'username' in params else '')
        config_key = (params['key'] if 'key' in params else '')

        # token认证和业务处理
        methods_need_token = [
            'query_devices', 'query_cameras', 'get_configs', 'get_config',
            'query_users', 'query_stage', 'query_system'
        ]

        if args not in methods_need_token or Util.certify_token(token):
            try:
                ret_code, ret_data = {
                    'query_devices':
                    lambda: vis_master.query_devices(),
                    'query_cameras':
                    lambda: vis_master.query_cameras(),
                    'get_configs':
                    lambda: vis_master.get_configs(),
                    'get_config':
                    lambda: vis_master.get_config(config_key),
                    'query_users':
                    lambda: vis_master.query_users(),
                    'query_stage':
                    lambda: vis_master.query_stage(),
                    'query_system':
                    lambda: vis_master.query_system(),
                }[args]()

                if args not in methods_disallow_log:
                    log.debug('ret_data:%s' % (ret_data))
            except KeyError:
                log.error('unknow key:%s' % (args))
                ret_code, ret_data = 1003, '{"info": "Invalid parameter."}'
            except Exception as e:
                log.error('exception:%s,%s' % (args, str(e)))
                ret_code, ret_data = 1008, '{"info": "Internal system error."}'
        else:
            ret_code, ret_data = 1002, '{"info": "Invalid token."}'

        # 拼接返回json数据
        if ret_data is None:
            ret = '{"code": "%d"}' % (ret_code)
        else:
            ret = '{"code": "%d", "data": %s}' % (ret_code, ret_data)

        return ret

    def POST(self, args):
        methods_disallow_log = []
        if args not in methods_disallow_log:
            log.debug('POST [%s][%s]' % (args, web.data()))

        # 返回码和数据
        ret_code, ret_data = 1000, None

        # 参数获取
        params = web.input()
        token = (str(params['token']) if 'token' in params else '')

        room_id = ''
        username = ''
        nickname = ''
        passwd = ''
        phone = ''
        email = ''
        company = ''
        role = ''

        if web.data():
            datas = json.loads(urllib.unquote(web.data()))
            device_name = (datas['name'] if 'name' in datas else '')
            device_ip = (datas['ip'] if 'ip' in datas else '')
            device_type = (int(datas['type'])
                           if 'type' in datas else Const.DEVICE_TYPE_ORG)
            device_parent = (int(datas['parent']) if 'parent' in datas else 0)
            username = (datas['username'] if 'username' in datas else '')
            nickname = (datas['nickname'] if 'nickname' in datas else '')
            passwd = (datas['passwd'] if 'passwd' in datas else '')
            phone = (datas['phone'] if 'phone' in datas else '')
            email = (datas['email'] if 'email' in datas else '')

        # token认证和业务处理
        methods_need_token = ['create_device', 'add_user']

        if args not in methods_need_token or Util.certify_token(token):
            try:
                ret_code, ret_data = {
                    'create_device':
                    lambda: vis_master.create_device(
                        device_name, device_ip, device_type, device_parent),
                    'add_user':
                    lambda: vis_master.add_user(username, nickname, passwd,
                                                phone, email),
                }[args]()

                if args not in methods_disallow_log:
                    log.debug('ret_data:%s' % (ret_data))
            except KeyError:
                log.error('unknow key:%s' % (args))
                ret_code, ret_data = 1003, '{"info": "Invalid parameter."}'
            except Exception as e:
                log.error('exception:%s,%s' % (args, str(e)))
                ret_code, ret_data = 1008, '{"info": "Internal system error."}'
        else:
            ret_code, ret_data = 1002, '{"info": "Invalid token."}'

        # 拼接返回json数据
        if ret_data is None:
            ret = '{"code": "%d"}' % (ret_code)
        else:
            ret = '{"code": "%d", "data": %s}' % (ret_code, ret_data)
        return ret

    def PUT(self, args):
        methods_disallow_log = []
        if args not in methods_disallow_log:
            log.debug('PUT [%s][%s]' % (args, web.data()))

        # 返回码和数据
        ret_code, ret_data = 1000, None

        # 参数获取
        params = web.input()
        token = (str(params['token']) if 'token' in params else '')

        room_id = ''
        forward_addr = ''
        record_id = ''
        file_name = ''
        config_key = ''
        config_value = ''
        username = ''
        passwd = ''
        old_passwd = ''
        new_passwd = ''

        if web.data():
            datas = json.loads(urllib.unquote(web.data()))
            config_key = (datas['key'] if 'key' in datas else '')
            config_value = (datas['value'] if 'value' in datas else '')
            username = (datas['username'] if 'username' in datas else '')
            passwd = (datas['passwd'] if 'passwd' in datas else '')
            old_passwd = (datas['old_passwd'] if 'old_passwd' in datas else '')
            new_passwd = (datas['new_passwd'] if 'new_passwd' in datas else '')
            split = (int(datas['split']) if 'split' in datas else 0)
            pos = (int(datas['pos']) if 'pos' in datas else -1)
            device_id = (int(datas['device_id'])
                         if 'device_id' in datas else -1)

        # token认证和业务处理
        methods_need_token = ['set_config', 'modify_password', 'set_stage']

        if args not in methods_need_token or Util.certify_token(token):
            try:
                ret_code, ret_data = {
                    'set_config':
                    lambda: vis_master.set_config(config_key, config_value),
                    'login':
                    lambda: vis_master.login(username, passwd),
                    'modify_password':
                    lambda: vis_master.modify_password(
                        username, old_passwd, new_passwd),
                    'set_stage_split':
                    lambda: vis_master.set_stage_split(split),
                    'set_stage_subscreen':
                    lambda: vis_master.set_stage_subscreen(pos, device_id),
                    'active_camera':
                    lambda: vis_master.active_camera(device_id),
                    'inactive_camera':
                    lambda: vis_master.inactive_camera(device_id),
                }[args]()

                if args not in methods_disallow_log:
                    log.debug('ret_data:%s' % (ret_data))
            except KeyError:
                log.error('unknow key:%s' % (args))
                ret_code, ret_data = 1003, '{"info": "Invalid parameter."}'
            except Exception as e:
                log.error('exception:%s,%s' % (args, str(e)))
                ret_code, ret_data = 1008, '{"info": "Internal system error."}'
        else:
            ret_code, ret_data = 1002, '{"info": "Invalid token."}'

        # 拼接返回json数据
        if ret_data is None:
            ret = '{"code": "%d"}' % (ret_code)
        else:
            ret = '{"code": "%d", "data": %s}' % (ret_code, ret_data)
        return ret

    def DELETE(self, args):
        methods_disallow_log = []
        if args not in methods_disallow_log:
            log.debug('DELETE [%s][%s]' % (args, web.data()))

        # 返回码和数据
        ret_code, ret_data = 1000, None

        # 参数获取
        params = web.input()
        token = (str(params['token']) if 'token' in params else '')

        room_id = ''
        record_id = ''
        username = ''

        if web.data():
            datas = json.loads(urllib.unquote(web.data()))
            device_id = (int(datas['device_id'])
                         if 'device_id' in datas else -1)
            username = (datas['username'] if 'username' in datas else '')

        # token认证和业务处理
        methods_need_token = ['delete_device', 'delete_user']

        if args not in methods_need_token or Util.certify_token(token):
            try:
                ret_code, ret_data = {
                    'delete_device': lambda: vis_master.delete_device(device_id),
                    'delete_user': lambda: vis_master.delete_user(username),
                }[args]()

                if args not in methods_disallow_log:
                    log.debug('ret_data:%s' % (ret_data))
            except KeyError:
                log.error('unknow key:%s' % (args))
                ret_code, ret_data = 1003, '{"info": "Invalid parameter."}'
            except Exception as e:
                log.error('exception:%s,%s' % (args, str(e)))
                ret_code, ret_data = 1008, '{"info": "Internal system error."}'
        else:
            ret_code, ret_data = 1002, '{"info": "Invalid token."}'

        # 拼接返回json数据
        if ret_data is None:
            ret = '{"code": "%d"}' % (ret_code)
        else:
            ret = '{"code": "%d", "data": %s}' % (ret_code, ret_data)
        return ret


class CallbackDispather:
    '''SRS Callback Dispather'''

    def GET(self, args):
        methods_disallow_log = ['on_hls_notify']
        if args not in methods_disallow_log:
            log.debug('GET [%s]' % args)

        # 返回数据
        ret_data = 1

        # 参数获取
        params = web.input()
        stream = (params['stream'] if 'stream' in params else '')
        ts_name = (params['ts_name'] if 'ts_name' in params else '')

        try:
            ret_data = {
                'on_hls_notify':
                    lambda: vis_master.on_hls_notify(stream, ts_name),
            }[args]()

            if args not in methods_disallow_log:
                log.debug('ret_data:%s' % (ret_data))
        except KeyError:
            log.error('unknow key:%s' % (args))
        except Exception as e:
            log.error('exception:%s,%s' % (args, str(e)))

        return ret_data

    def POST(self, args):
        methods_disallow_log = ['on_connect', 'on_close', 'on_play', 'on_stop']
        if args not in methods_disallow_log:
            log.debug('POST [%s][%s]' % (args, web.data()))

        # 返回数据
        ret_data = 1

        try:
            ret_data = {
                'flv_finish':
                lambda: vis_master.flv_finish(web.data()),
                'on_connect':
                lambda: vis_master.on_connect(web.data()),
                'on_close':
                lambda: vis_master.on_close(web.data()),
                'on_publish':
                lambda: vis_master.on_publish(web.data()),
                'on_unpublish':
                lambda: vis_master.on_unpublish(web.data()),
                'on_play':
                lambda: vis_master.on_play(web.data()),
                'on_stop':
                lambda: vis_master.on_stop(web.data()),
            }[args]()

            if args not in methods_disallow_log:
                log.debug('ret_data:%s' % (ret_data))
        except KeyError:
            log.error('unknow key:%s' % (args))
        except Exception as e:
            log.error('exception:%s,%s' % (args, str(e)))

        return ret_data


class Restful():
    '''RESTful service for VIS'''

    def __init__(self, master_instance):
        global vis_master
        vis_master = master_instance

    def run_app(self):
        log.info('VIS restful service start...')
        app.run()
